package com.daojia.daojiasync.service;


import com.daojia.daojiasync.Utils.TimeUtils;
import com.daojia.daojiasync.dao.WorkOrderRepository;
import com.daojia.daojiasync.dto.ApiResponse;
import com.daojia.daojiasync.entity.WorkOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WorkOrderService {

    @Value("${api.token:8de55b8b96fd00061df5ba270f7c37ac}")
    private String token;

    @Value("${api.base-url:https://gd.rrskjfw.com.cn}")
    private String baseUrl;

    @Autowired
    private WorkOrderRepository workOrderRepository;

    @Autowired
    private RestTemplate restTemplate;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public List<WorkOrder> getOrdersFromApi() {
        String url = baseUrl + "/rrs-ticket/rrs/worder/worderinformation/orderAll";

        HttpHeaders headers = new HttpHeaders();
        headers.set("authority", "gd.rrskjfw.com.cn");
        headers.set("accept", "application/json, text/plain, */*");
        headers.set("accept-language", "zh-CN,zh;q=0.9");
        headers.set("priority", "u=1, i");
        headers.set("sec-ch-ua", "\"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\", \"Not_A Brand\";v=\"99\"");
        headers.set("sec-ch-ua-mobile", "?0");
        headers.set("sec-ch-ua-platform", "\"Windows\"");
        headers.set("sec-fetch-dest", "empty");
        headers.set("sec-fetch-mode", "cors");
        headers.set("sec-fetch-site", "same-origin");
        headers.set("token", token);
        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36");

        Map<String, String> params = new HashMap<>();
        params.put("page", "1");
        params.put("limit", "50");
//        params.put("startTime", startTime);
//        params.put("endTime", endTime);

        HttpEntity<String> httpEntity = new HttpEntity<>(headers);

        String fullUrl = url + "?" + buildQueryString(params);
        ResponseEntity<ApiResponse> response = restTemplate.exchange(fullUrl, HttpMethod.GET, httpEntity, ApiResponse.class);

        if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
            List<ApiResponse.WorkOrderItem> items = response.getBody().getPage().getList();
            return items.stream().map(WorkOrder::flattenOrder).collect(Collectors.toList());
        }

        return Collections.emptyList();
    }


    private LocalDateTime parseDateTime(String dateTimeStr) {
        if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
            return null;
        }
        try {
            return LocalDateTime.parse(dateTimeStr, DATE_TIME_FORMATTER);
        } catch (Exception e) {
            return null;
        }
    }

    private String buildQueryString(Map<String, String> params) {
        return params.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }

    public void syncWorkOrders() {
        List<WorkOrder> srcOrders = getOrdersFromApi();
        if (srcOrders.isEmpty()) {
            log.info("源端未查询到数据！");
            return;
        }
        srcOrders.sort(Comparator.comparingLong(WorkOrder::getCreateTimeForNum));

        List<WorkOrder> dbOrders = workOrderRepository.findByCreateTimeBetween(srcOrders.get(0).getCreateTime(), srcOrders.get(srcOrders.size() - 1).getCreateTime());
        handle(srcOrders, dbOrders);
    }

    private void handle(List<WorkOrder> srcOrders, List<WorkOrder> dbOrders) {
        LocalDateTime lastTime = dbOrders.isEmpty() ? TimeUtils.parseDateTime("1970-01-01") : dbOrders.get(dbOrders.size() - 1).getCreateTime();

        //新增数据
        //数据库最新时间之后的数据
        List<WorkOrder> workOrderListToInsert = srcOrders.stream().filter(workOrder -> workOrder.getCreateTime().isAfter(lastTime)).collect(Collectors.toList());
        //批量插入
        workOrderRepository.saveAll(workOrderListToInsert);

        List<String> dbOrdersWorderNoList = dbOrders.stream().map(WorkOrder::getWorderNo).collect(Collectors.toList());
        List<String> srcWorderNoList = srcOrders.stream().map(WorkOrder::getWorderNo).collect(Collectors.toList());

        //消失数据
        //求差集 使用数据库数据-源数据
        Collection<String> dbOrdersWorderNoListSubtract = CollectionUtils.subtract(dbOrdersWorderNoList, srcWorderNoList);
        for (String worderNo : dbOrdersWorderNoListSubtract) {
            workOrderRepository.updateSysMarkByWorderNo(worderNo, String.format("消失的工单-标记时间:%s", System.currentTimeMillis()));
        }

        //
        //漏写入的数据
        //求差集 源数据-数据库数据
        Collection<String> srcOrdersWorderNoListSubtract = CollectionUtils.subtract(srcWorderNoList, dbOrdersWorderNoList);
        List<WorkOrder> srcWorkOrderList = dbOrders.stream().filter(workOrder -> srcOrdersWorderNoListSubtract.contains(workOrder.getWorderNo())).collect(Collectors.toList());
        //批量写入
        workOrderRepository.saveAll(srcWorkOrderList);

    }

    private void compareAndUpdateOrders(List<WorkOrder> srcOrders, List<WorkOrder> dbOrders) {
        Map<String, WorkOrder> srcOrdersMap = srcOrders.stream()
                .collect(Collectors.toMap(WorkOrder::getWorderNo, order -> order));

        Map<String, WorkOrder> dbOrdersMap = dbOrders.stream()
                .collect(Collectors.toMap(WorkOrder::getWorderNo, order -> order));

        LocalDateTime latestDbTime = workOrderRepository.findMaxCreateTime();
        if (latestDbTime == null) {
            latestDbTime = LocalDateTime.of(1970, 1, 1, 0, 0);
        }

        SyncStats stats = new SyncStats();

        // 处理数据库中存在的数据
        for (Map.Entry<String, WorkOrder> entry : dbOrdersMap.entrySet()) {
            String dbOrderNo = entry.getKey();
            WorkOrder dbOrder = entry.getValue();

            if (srcOrdersMap.containsKey(dbOrderNo)) {
                WorkOrder srcOrder = srcOrdersMap.get(dbOrderNo);
                List<String> changes = checkOrderChanges(srcOrder, dbOrder);

                if (!changes.isEmpty()) {
                    updateOrderWithChanges(srcOrder, changes);
                    stats.updated++;
                    System.out.println("✅ 更新订单: " + dbOrderNo + ", 变化: " + changes);
                } else {
                    stats.unchanged++;
                    System.out.println("➖ 订单无变化: " + dbOrderNo);
                }

                srcOrdersMap.remove(dbOrderNo);
            } else {
                markOrderAsTransferred(dbOrderNo);
                stats.transferred++;
                System.out.println("🚨 订单被转移: " + dbOrderNo);
            }
        }

        // 处理新增数据
        for (WorkOrder srcOrder : srcOrdersMap.values()) {
            if (latestDbTime == null || latestDbTime.isBefore(srcOrder.getCreateTime())) {
                insertNewOrderWithMark(srcOrder, "新增订单");
                stats.inserted++;
                System.out.println("🆕 新增订单: " + srcOrder.getWorderNo());
            } else {
                insertNewOrderWithMark(srcOrder, "新增订单,之前漏同步");
                stats.transferred++;
                System.out.println("⚠️ 时间异常订单,可能是之前漏同步的订单: " + srcOrder.getWorderNo());
            }
        }

        printSyncStats(stats);
    }

    private List<String> checkOrderChanges(WorkOrder srcOrder, WorkOrder dbOrder) {
        List<String> changes = new ArrayList<>();

        // 比较各个字段，这里简化实现，实际需要比较所有字段
        if (!Objects.equals(normalizeValue(srcOrder.getAddress()), normalizeValue(dbOrder.getAddress()))) {
            changes.add("address: " + formatValue(dbOrder.getAddress()) + " -> " + formatValue(srcOrder.getAddress()));
        }

        // 继续比较其他字段...

        return changes;
    }

    private String normalizeValue(Object value) {
        if (value == null) {
            return "";
        }
        if (value instanceof Boolean) {
            return ((Boolean) value) ? "true" : "false";
        }
        return value.toString().trim().toLowerCase();
    }

    private String formatValue(Object value) {
        if (value == null) {
            return "空";
        }
        if (value instanceof Boolean) {
            return (Boolean) value ? "是" : "否";
        }
        return value.toString();
    }

    private void updateOrderWithChanges(WorkOrder order, List<String> changes) {
        String changesStr = String.join("; ", changes);
        String currentTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
        order.setSysMark("数据同步更新: " + changesStr + " - 标记时间: " + currentTime);
        workOrderRepository.save(order);
    }

    private void insertNewOrderWithMark(WorkOrder order, String mark) {
        String currentTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
        order.setSysMark("数据同步" + mark + " - 标记时间: " + currentTime);
        workOrderRepository.save(order);
    }

    private void markOrderAsTransferred(String orderNo) {
        String currentTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
        String sysMark = "数据同步发现订单被转移 - 标记时间: " + currentTime;
        workOrderRepository.updateSysMarkByWorderNo(orderNo, sysMark);
    }

    private void printSyncStats(SyncStats stats) {
        System.out.println("\n同步完成统计:");
        System.out.println("新增: " + stats.inserted + " 条");
        System.out.println("更新: " + stats.updated + " 条");
        System.out.println("转移: " + stats.transferred + " 条");
        System.out.println("无变化: " + stats.unchanged + " 条");
        int total = stats.inserted + stats.updated + stats.transferred + stats.unchanged;
        System.out.println("总计处理: " + total + " 条");
    }

    private static class SyncStats {
        int inserted = 0;
        int updated = 0;
        int transferred = 0;
        int unchanged = 0;
    }
}